package com.cyrusInnovation.test.formatter;

import java.text.DateFormat;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Date;
import java.util.StringTokenizer;

import com.cyrusInnovation.test.record.Gender;
import com.cyrusInnovation.test.record.PersonRecord;

/**
 * The DelimiterRecordFormatter formats <code>PersonRecord</code> 
 * to and from delimited <code>String</code>.
 * <p>
 * The sub class must implements the <code>init</code> method to define
 * <ul>
 * <li>The delimiter string
 * <li>How the tokens in the string are mapped to data elements in the <code>PersonRecord</code>
 * <li>Date format
 * </ul>
 * <p>
 *
 * @author  Al
 * @see     com.cyrusInnovation.test.formatter.PipeRecordFormatter
 */

public abstract class DelimiterRecordFormatter implements PersonRecordFormatter{

	protected String delimiter;
	protected DateFormat dtFormat;
	protected int lastNamePosition;
	protected int firstNamePosition;
	protected int genderPosition;
	protected int dateOfBirthPosition;
	protected int favoriteColorPosition;

	public DelimiterRecordFormatter() {
		init();
	}
	
	public abstract void init();

	/**
	 * Create a formatted string from the <code>personRecord</code> passed in
	 * @param record 	a personRecord to be formatted
	 * @return 			String in the specified format
	 */
	public String PersonRecordToString(PersonRecord record) {
		if (record==null){return "";}
		
		//init dataElements
		String[] dataElements=new String[getDataElementMaxSize()];
		Arrays.fill(dataElements, "");
		
		//populate dataElements according to the mapping
		dataElements[lastNamePosition]=record.getLastName();
		dataElements[firstNamePosition]=record.getFirstName();
		Gender gender = record.getGender();
		if (gender!=Gender.UNKNOWN){
			dataElements[genderPosition]=record.getGender().getName();
		}
		Date DateOfBirth = record.getDateOfBirth();
		if (DateOfBirth!=null) {
			dataElements[dateOfBirthPosition]=dtFormat.format(record.getDateOfBirth());
		}
		dataElements[favoriteColorPosition]=record.getFavoriteColor();
		
		//cancate dataElements into string using delimiter
		String str=dataElements[0];
		for (int i=1;i<dataElements.length; i++){
			str=str+delimiter+dataElements[i];
		}
		return str;
	}
	
	/**
	 * Create a personRecord from the data in the string passed in
	 * @param str a string to be parsed
	 * @return personRecord populated with data from str
	 */
	public PersonRecord StringToPersonRecord(String str) {
		StringTokenizer strTokenizer=new StringTokenizer(str,delimiter);
		String[] dataElements=new String[getDataElementMaxSize()];
		Arrays.fill(dataElements, "");
		for (int i=0; (i <dataElements.length) && strTokenizer.hasMoreTokens(); i++ ){
			dataElements[i]=strTokenizer.nextToken().trim();
		}
		PersonRecord record = new PersonRecord();
		record.setLastName(dataElements[lastNamePosition]);
		record.setFirstName(dataElements[firstNamePosition]);
		record.setGender(Gender.fromString(dataElements[genderPosition]));
		record.setFavoriteColor(dataElements[favoriteColorPosition]);
		try {
			record.setDateOfBirth(dtFormat.parse(dataElements[dateOfBirthPosition]));			
		} catch (ParseException  e) {
			record.setDateOfBirth(null);
		} 
		return record;
	}
	
	private int getDataElementMaxSize() {
		int maxPosition=0;
		maxPosition=Math.max(lastNamePosition,maxPosition);
		maxPosition=Math.max(firstNamePosition,maxPosition);
		maxPosition=Math.max(genderPosition,maxPosition);
		maxPosition=Math.max(dateOfBirthPosition,maxPosition);
		maxPosition=Math.max(favoriteColorPosition,maxPosition);
		return maxPosition+1;
	}

}